package com.panfeng.xcloud.boss.provider.member.security.password;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.panfeng.xcloud.boss.provider.member.security.SecurityConstants;
import com.panfeng.xcloud.common.core.enums.ResponseStatusEnum;
import com.panfeng.xcloud.common.core.web.vo.ResponseVO;
import com.panfeng.xcloud.common.security.utils.BCryptPasswordUtils;
import com.panfeng.xcloud.common.security.vo.SysSecurityUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;

@Component("pwdAuthenticationSuccessHandler")
@Slf4j
public class PwdAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Resource
	private ObjectMapper objectMapper;

	@Resource
	private ClientDetailsService clientDetailsService;

	@Resource
	private AuthorizationServerTokenServices authorizationServerTokenServices;

	private String clientIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_CLIENTID;
	private String clientSecretParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_CLIENTSECRET;

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
		log.info(">>> pwdAuthenticationSuccessHandler==>登录成功");
		String clientId = getClientId(request);
		String clientSecret = getClientSecret(request);
		log.info(">>>> 开始执行pwdAuthenticationSuccessHandler鉴权成功处理器，clientId：{}<<<",clientId);
		ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
		if (clientDetails == null) {
			log.error(">>>> 执行pwdAuthenticationSuccessHandler鉴权成功处理器异常：clientId对应的配置信息不存在: {} <<<",clientId);
			throw new UnapprovedClientAuthenticationException("clientId对应的配置信息不存在:" + clientId);
		} else if (!BCryptPasswordUtils.matches(clientSecret, clientDetails.getClientSecret())) {
			log.error(">>>> 执行pwdAuthenticationSuccessHandler鉴权成功处理器异常：clientSecret不匹配:{} <<<",clientId);
			throw new UnapprovedClientAuthenticationException("clientSecret不匹配:" + clientId);
		}
		TokenRequest tokenRequest = new TokenRequest(new HashMap<String, String>(), clientId, clientDetails.getScope(), "custom");
		OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
		OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
		OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
		SysSecurityUser principal = (SysSecurityUser) authentication.getPrincipal();
		log.info(">>> 执行pwdAuthenticationSuccessHandler鉴权成功处理器,获取登录信息，账户名:{}，用户id:{}", principal.getUsername(),principal.getUserId());
		response.setContentType("application/json;charset=UTF-8");
		ResponseVO responseVO = new ResponseVO();
		responseVO.setCode(ResponseStatusEnum.OK.getCode());
		responseVO.setMessage(ResponseStatusEnum.OK.getMessage());
		responseVO.setData(token);
		response.getWriter().write((objectMapper.writeValueAsString(responseVO)));
	}

	private String getClientSecret(HttpServletRequest request) {
		return request.getParameter(clientSecretParameter);
	}

	private String getClientId(HttpServletRequest request) {
		return request.getParameter(clientIdParameter);
	}

}
